﻿namespace WebPacker.Filters
{
	using System;
	using System.Collections.Generic;
	using WebPacker.Packs;

	public sealed class FilterCollection : ICollection<IFilter>
	{
		private readonly IList<IFilter> items;

		public FilterCollection()
		{
			items = new List<IFilter>();
		}

		public int Count
		{
			get { return items.Count; }
		}

		public bool IsReadOnly
		{
			get { return false; }
		}

		public IFilter GetItem(PackType packType)
		{
			return GetItem(packType, null);
		}

		public IFilter GetItem(PackType packType, string filterName)
		{
			var index = IndexOf(packType, filterName);

			if (index == -1)
			{
				throw new ArgumentException(string.Format("Filter \"{0}\" for \"{1}\" isn't found.", filterName, packType));
			}

			return items[index];
		}

		public bool TryGetItem(PackType packType, out IFilter filter)
		{
			return TryGetItem(packType, null, out filter);
		}

		public bool TryGetItem(PackType packType, string filterName, out IFilter filter)
		{
			var index = IndexOf(packType, filterName);

			filter = null;

			if (index != -1)
			{
				filter = items[index];
			}

			return filter != null;
		}

		public void Add(IFilter item)
		{
			if (item == null)
			{
				throw new ArgumentNullException("item");
			}

			var index = IndexOf(item.PackType, item.Name);

			if (index != -1)
			{
				throw new ArgumentException(string.Format("Filter \"{0}\" for \"{1}\" is registered allready.", item.Name, item.PackType));
			}

			items.Add(item);
		}

		public void AddRange(IEnumerable<IFilter> items)
		{
			if (items == null)
			{
				throw new ArgumentNullException("items");
			}

			foreach (var item in items)
			{
				Add(item);
			}
		}

		public void Clear()
		{
			items.Clear();
		}

		public bool Contains(PackType packType, string filterName)
		{
			return IndexOf(packType, filterName) != -1;
		}

		public bool Contains(IFilter item)
		{
			return items.Contains(item);
		}

		public void CopyTo(IFilter[] array, int arrayIndex)
		{
			items.CopyTo(array, arrayIndex);
		}

		public bool Remove(IFilter item)
		{
			return items.Remove(item);
		}

		public bool Remove(PackType packType, string filterName)
		{
			if (filterName == null)
			{
				throw new ArgumentNullException("filterName");
			}

			var index = IndexOf(packType, filterName);
			var exists = index != -1;

			if (exists)
			{
				items.RemoveAt(index);
			}

			return exists;
		}

		public IEnumerator<IFilter> GetEnumerator()
		{
			return items.GetEnumerator();
		}

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return items.GetEnumerator();
		}

		private int IndexOf(PackType packType, string filterName)
		{
			var index = -1;

			for (var i = 0; i < items.Count; i++)
			{
				var item = items[i];

				if (item.PackType == packType)
				{
					if (filterName == null || 0 == string.Compare(item.Name, filterName, StringComparison.CurrentCulture))
					{
						index = i;
						break;
					}
				}
			}

			return index;
		}
	}
}